package com.blue.base.common.utils.json;

import com.blue.base.common.bean.resp.JsonResult;
import com.blue.base.common.exception.BaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;

import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 异常处理分层工具类：保证自定义异常抛出，又避免系统500类型异常直接返回给前端
 *
 * @author liulei
 * @version 1.0
 */
public class ResponseUtil<T, R> {

    private static final Logger log = LoggerFactory.getLogger(JsonResult.class);

    /**
     * controller层带异常统一返回
     *
     * @param executor         执行器-service返回resp包装的结果[带自定义异常抛出]
     * @param errorDescription 出现程序错误500侯，接口的整体错误描述
     * @return resp
     */
    public static <T> JsonResult<T> returnWithException(Supplier<JsonResult<T>> executor, String errorDescription) {
        JsonResult<T> result;
        try {
            result = executor.get();
            result.setStatus(200);
        } catch (BaseException e) {
            log.error("业务异常", e);
            throw e;
        } catch (Exception e) {
            log.error("系统异常", e);
            throw new BaseException(HttpStatus.INTERNAL_SERVER_ERROR.value(), errorDescription);
        }
        return result;
    }

    /**
     * controller层出现系统异常统一返回默认对象，自定义异常则抛出
     *
     * @param executor     执行器-service返回resp包装的结果[带自定义异常抛出]
     * @param defaultValue 出现程序错误500后，以默认值/对象返回
     * @return resp
     */
    public static <T> JsonResult<T> returnDefaultValue(Supplier<JsonResult<T>> executor, T defaultValue) {
        JsonResult<T> result = new JsonResult<>();
        result.setStatus(200);
        try {
            result = executor.get();
        } catch (Exception e) {
            log.error("系统异常", e);
            result.setData(defaultValue);
        }
        return result;
    }

    /**
     * 获取远程调用接口返回值，并做异常处理
     *
     * @param param        入参
     * @param invokeAction 调用函数
     * @return 操作结果
     */
    public static <T, R> JsonResult<R> wrapRemoteInvoke(T param, Function<T, JsonResult<R>> invokeAction) {
        JsonResult<R> operateJsonResult;
        try {
            operateJsonResult = invokeAction.apply(param);
        } catch (Exception e) {
            log.info("remote|invoke|api|to|remote|failed|{}", JsonUtil.toJson(param), e);
            throw new RuntimeException("远程接口调用失败");
        }
        if (operateJsonResult == null || operateJsonResult.getStatus() != HttpStatus.OK.value()) {
            log.info("remote|invoke|api|to|bus|error|{}", JsonUtil.toJson(operateJsonResult));
            throw new RuntimeException("远程接口内部异常");
        }
        return operateJsonResult;
    }
}
